﻿#include "GameScene.h"
#include "StartScene.h"
#include <iostream>
#include "hero/Hero.h"
#include "enemy/Enemy.h"
#include "enemy/EnemyManager.h"
#include "bullet/Bullet.h"
#include "bullet/BulletManager.h"
#include "enemy/EnemyManager.h"
#include "coin/Coin.h"
#include "coin/CoinManager.h"
#include "utils/LevelUtils.h"
#include "utils/AudioUtil.h"
#include "prop/Prop.h"
#include "prop/PropManager.h"
#include "prop/PropTip.h"
#include "prop/PropTipManager.h"
USING_NS_CC;
#define GAME_BG 40
using namespace cocos2d;
using namespace cocos2d::ui;
using namespace cocostudio::timeline;

Scene* GameScene::createScene()
{
    auto scene = Scene::create();
    auto layer = GameScene::create();
    scene->addChild(layer);
    return scene;
}

bool GameScene::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
	totalCoin = UserDefault::getInstance()->getIntegerForKey("coin", 0);
	initCSBFile();
	initGameBg();
	initLevel();
	//开启创建病毒调度器
	
	scheduleOnce(schedule_selector(GameScene::delayInitHeroUpdate), 2);

    return true;
}

void GameScene::onEnter() {
	Layer::onEnter();
	_eventDispatcher->addCustomEventListener("onCoinActFinish", [this](EventCustom* event) {
		//金币动画完成后增加金币数
		Coin* coin = (Coin*)event->getUserData();
		this->addCoin(coin->getCoinNum(), coin->getIsGameCoin());
	});
	_eventDispatcher->addCustomEventListener("onEnemyDeath", [this](EventCustom* event) {
		//当病毒死亡后分发消息
		currentEnemyCount--;
		Enemy* userData = (Enemy*)event->getUserData();



		//如果病毒的等级大于1，死亡后分裂为其两个等级-1的小病毒
		EnemyLevel level = userData->getEnemyLevel();
		Vec2 currentPos = userData->getEnemyPos();
		int enemyPosX = currentPos.x + userData->getEnemyInitPos().x;
		int enemyPosY = currentPos.y + userData->getEnemyInitPos().y;
		Size enemySize = userData->getEnemySize();
		Vec2 enemyPos = Vec2(enemyPosX, enemyPosY);
		//增加金钱逻辑
		addCoinAction(enemyPos, userData->getEnemySize(), userData->getCoin(), level);
		int flag = 1;
		if (userData->getEnemyLevel() > Level_1) {
			for (int i = 1; i <= 2; i++) {
				flag = flag * -1;
				Enemy* enemy = Enemy::create(CommonVirus, (EnemyLevel)(level - 1));
				int moveX = enemyPosX + enemySize.width / 4 * flag;
				//int moveX = enemyPosX + rand() % (int)(enemySize.width / 4) - enemySize.width / 8;
				//int moveY = enemyPosX + rand() % (int)(enemySize.height / 4) - enemySize.height / 8;
				int moveY = enemyPosY + enemySize.height / 4;
				Vec2 enemyMove = Vec2(moveX, moveY);
				MoveTo* mt = MoveTo::create(0.4f, enemyMove);
				ScaleTo* st = ScaleTo::create(0.4f, 1.0);
				enemy->setScale(0.5);
				enemy->setEnemyPos(enemyMove);
				enemy->setPosition(enemyPos);
				enemy->setZOrder(2);
				this->addChild(enemy);
				enemy->runAction(mt);
				enemy->runAction(st);
				EnemyManager::getInstance()->addEnemy(enemy);
			}
		}

		//随机创建道具
		srand(time(nullptr));
		int r = rand() % 7;
		if (r == 3) {
			//十分之一的概率产生道具
			int type = rand() % 9;
			if (PropType(type + 1) == CallSupport || PropType(type + 1) == RepulsiveShooting ||
				PropType(type + 1) == MegaloVirus || PropType(type + 1) == RestrictMovement) {
				//这四个道具暂时没做
			} else {
				Prop* prop = Prop::create(PropType(type + 1));
				prop->setPosition(enemyPos);
				prop->setPropInitPos(enemyPos);
				prop->setZOrder(2);
				addChild(prop);
				PropManager::getInstance()->addProp(prop);
			}
			
		}
	});
}

void GameScene::onExit() {
	Layer::onExit();
	
	EnemyManager::getInstance()->clearList();
	CoinManager::getInstance()->clearList();
	BulletManager::getInstance()->clearList();
	PropManager::getInstance()->clearList();
	PropTipManager::getInstance()->clearList();

	//移出自定义监听器
	_eventDispatcher->removeCustomEventListeners("onEnemyDeath");
	_eventDispatcher->removeCustomEventListeners("onCoinActFinish");
}
/*
	加载csb文件
*/
void GameScene::initCSBFile() {
	size = Director::getInstance()->getVisibleSize();
	rootNode = CSLoader::createNode("scenes/game/scene/GameScene.csb");
	rootNode->setZOrder(3);
	addChild(rootNode);
	uiNode = dynamic_cast<Node*>(rootNode->getChildByName("uiNode"));
	levelNode = dynamic_cast<Node*>(rootNode->getChildByName("level"));
	progress_num = dynamic_cast<TextAtlas*>(uiNode->getChildByName("progress_num"));//消灭病毒百分比信息
	coin_num = dynamic_cast<Text*>(uiNode->getChildByName("coin_num"));//消灭病毒百分比信息
	progress = dynamic_cast<LoadingBar*>(uiNode->getChildByName("progress"));//消灭病毒百分比信息
	
}

/*
	初始化英雄
*/
void GameScene::initHero() {
	hero = Hero::getInstance();
	hero->setPosition(Vec2(size.width / 2, -100));
	hero->setZOrder(2);
	this->addChild(hero);
	MoveTo* mt = MoveTo::create(0.5, Vec2(size.width / 2, size.height / 10 * 3));
	hero->runAction(mt);
	hero->isOpenShoot(true, 0.6);
	hero->onTouchBeganCall = [this]() {
		resumeGame();
	};

	hero->onTouchEndedCall = [this]() {
		pauseGame();
	};
}

/*
	加载游戏背景
*/
void GameScene::initGameBg() {
	bg = Sprite::create("scenes/game/image/bg/bg_2.png");
	bg->setPosition(Vec2(size.width / 2, size.height / 2 - 15));
	bg->setScale(0.5);
	bg->setZOrder(1);
	this->addChild(bg);

}

/*
	初始化结算节点
*/
void GameScene::initSettlementNode() {
	//游戏背景变暗
	bg->setOpacity(150);
	Node* topCoinNode = dynamic_cast<Node*>(rootNode->getChildByName("coin"));
	topCoinNode->setVisible(true);
	topCoinNum = dynamic_cast<Text*>(topCoinNode->getChildByName("coin_num"));
	topCoinNum->setString(coinToString(totalCoin));
	Node* topStrengthNode = dynamic_cast<Node*>(rootNode->getChildByName("strength"));
	topStrengthNode->setVisible(true);

	settlementNode = dynamic_cast<Node*>(rootNode->getChildByName("settlementNode"));
	settlementNode->setVisible(true);
	MoveTo* mt = MoveTo::create(0.7, Vec2(size.width / 2, size.height / 2));
	settlementNode->runAction(mt);

	Text* coin_num = dynamic_cast<Text*>(settlementNode->getChildByName("coin_num"));
	coin_num->setString(coinToString(coin));
	Text* moreCoin_num = dynamic_cast<Text*>(settlementNode->getChildByName("moreCoin_num"));
	moreCoin_num->setString(coinToString(coin * 3));

	vector<Node*> coinNode;
	char fileName[40];
	for (size_t i = 0; i < 2; i++) {
		sprintf_s(fileName, "coin_%d", i + 1);
		coinNode.push_back(dynamic_cast<Node*>(settlementNode->getChildByName(fileName)));
		Sprite* coinSp = dynamic_cast<Sprite*>(coinNode[i]->getChildByName("coin"));
		ActionTimeline* coinAct = CSLoader::createTimeline("scenes/game/ui/coin.csb");
		coinAct->play("coinAct", true);
		coinSp->runAction(coinAct);
	}

	Button* getCoinBtn = dynamic_cast<Button*>(settlementNode->getChildByName("getCoinBtn"));
	getCoinBtn->addClickEventListener([this, getCoinBtn](Ref*) {
		//获取金币后返回主界面
		int coinCount = coin / 100;
		Vec2 pos = settlementNode->convertToWorldSpace(getCoinBtn->getPosition());
		Size btnSize = getCoinBtn->getContentSize();
		addCoinAction(pos, btnSize, 100, coinCount, false);
		//延迟返回开始界面
		scheduleOnce(schedule_selector(GameScene::delayBackStartSenceUpdate),3);
	});
}

/*
	初始化关卡节点 
*/
void GameScene::initLevel() {
	char filename[20];
	int value;
	for (size_t i = 0; i < 3; i++) {
		sprintf_s(filename, "num_%d", i + 1);
		TextAtlas* num = dynamic_cast<TextAtlas*>(levelNode->getChildByName(filename));
		levelNums.push_back(num);
		int level = UserDefault::getInstance()->getIntegerForKey(filename, i + 1);
		levelNums[i]->setString(std::to_string(level));
		if (1 == i) {
			value = level;
		}
	}
	//int value = atoi(levelNums[1]->getStringValue().data());
	//初始化病毒生产信息
	productEnemyCount = LevelUtils::getInstance()->getEnemyCount(value);
	totalEnemyCount = LevelUtils::getInstance()->getTotalEnemyCount(value);
	currentEnemyCount = totalEnemyCount;
	enemyLevels = LevelUtils::getInstance()->getEnemyLevel(value);
}

/*
	用于缓存plist文件
*/
void GameScene::initSpriteFrameCache() {

}

/*
	创建病毒调度器
*/
void GameScene::createEnemyUpdate(float dt) {
	//创建病毒
	Enemy* enemy = Enemy::create(CommonVirus, (EnemyLevel)enemyLevels[enemyLevels.size() - productEnemyCount]);
	int enemyWidth = enemy->getContentSize().width / 2;
	int enemyHeight = enemy->getContentSize().width / 2;
	Vec2 pos = Vec2(rand() % (500 - enemyWidth) + enemyWidth, size.height + enemyHeight);
	enemy->setEnemyPos(pos);
	enemy->setPosition(pos);
	enemy->setZOrder(2);
	this->addChild(enemy);
	EnemyManager::getInstance()->addEnemy(enemy);
	productEnemyCount--;
	if (productEnemyCount < 1) {
		unschedule(schedule_selector(GameScene::createEnemyUpdate));
	}
}

/*
	延迟初始化主机调度器
*/
void GameScene::delayInitHeroUpdate(float dt) {
	initHero();
	schedule(schedule_selector(GameScene::createEnemyUpdate), 1, -1, 0);
	//开启碰撞检测调度器
	scheduleUpdate();
	//开启BGM 
	AudioUtil::getInstence()->playBgm();
}

/*
	延迟返回开始场景调度器
*/
void GameScene::delayBackStartSenceUpdate(float dt) {
	if (hero->getHeroState()) {
		MoveTo* mt = MoveTo::create(0.5, Vec2(hero->getPositionX(), 1100));
		CallFunc* call = CallFunc::create([this]() {
			//关闭背景音乐
			AudioUtil::getInstence()->stopBgm();
			UserDefault::getInstance()->setIntegerForKey("coin", totalCoin);
			hero->collectionHero();
			Scene* startScene = StartScene::createScene();
			auto reSence = TransitionFade::create(1, startScene);
			Director::getInstance()->replaceScene(reSence);
		});
		Sequence* seqAct = Sequence::create(mt, call, nullptr);
		hero->runAction(seqAct);
	} else {
		//关闭背景音乐
		AudioUtil::getInstence()->stopBgm();
		UserDefault::getInstance()->setIntegerForKey("coin", totalCoin);
		hero->collectionHero();
		Scene* startScene = StartScene::createScene();
		auto reSence = TransitionFade::create(1.5, startScene);
		Director::getInstance()->replaceScene(reSence);
	}
}


/*
	默认调度器，用来进行碰撞检测
*/
void GameScene::update(float dt) {
	checkCurrentEnemyCount();
	collisionBulletAndEenmy();
	collisionHeroAndEenmy();
	collisionHeroAndProp();
}

/*
	英雄子弹与敌机碰撞检测
*/
void GameScene::collisionBulletAndEenmy() {
	for (Enemy* enemy : EnemyManager::getInstance()->enemyList) {
		bool isCrash = false;
		
		for (Bullet* bullet : BulletManager::getInstance()->heroLives) {
			//如果enemy为死亡状态
			if (!enemy->getLive() || !bullet->getLive()) {
				continue;
			}
			auto enemyRect = enemy->getEnemyRect();
			auto bulletRect = bullet->getBulletRect();
			isCrash = bulletRect.intersectsRect(enemyRect);
			if (isCrash) {
				pwCount++;
				bullet->setLive(false);//设置子弹死亡
				//判断是否开启点石成金效果
				if (hero->getPerformWondersState() && pwCount >= 20) {
					//如果病毒的等级大于1，死亡后分裂为其两个等级-1的小病毒
					EnemyLevel level = enemy->getEnemyLevel();
					Vec2 currentPos = enemy->getEnemyPos();
					int enemyPosX = currentPos.x + enemy->getEnemyInitPos().x;
					int enemyPosY = currentPos.y + enemy->getEnemyInitPos().y;
					Vec2 enemyPos = Vec2(enemyPosX, enemyPosY);
					//增加金钱逻辑
					addCoinAction(enemyPos, enemy->getEnemySize(), enemy->getCoin(), 1, true, true);
					pwCount = 0;
				}

				if (bullet->getBulletType() == WeaponBullet) {
					enemy->hurt(hero->getWeaponAtk());//设置病毒受伤
				} else {
					enemy->hurt(hero->getAtk());//设置病毒受伤
				}
				enemy->slowSpeed();//病毒减速
				break;
			}
		}
	}
}

/*
	主机与道具的碰撞检测
*/
void GameScene::collisionHeroAndProp(){
	for (Prop* prop : PropManager::getInstance()->propList) {
		//如果道具为死亡状态
		if (!prop->getLiveState()) {
			continue;
		}
		if (hero->getHeroState()) {
			bool isCrash = hero->getHeroRect().intersectsRect(prop->getPropRect());
			if (isCrash) {
				prop->setLiveState(false);//道具消失
				if (!PropTipManager::getInstance()->isPropInPropTip(prop->getPropType())) {
					PropTip* propTip = PropTip::create(prop->getPropType());
					addChild(propTip);
					propTip->setZOrder(2);
					PropTipManager::getInstance()->addPropTip(propTip);
					int count = PropTipManager::getInstance()->getPropListNumber();
					float posX = size.width - propTip->getPropTipSize().width / 2 - 15;
					float posY = size.height - ((propTip->getPropTipSize().height + 15) * count);
					propTip->setPosition(Vec2(posX, posY));
					propEff(propTip);
				} else {
					//如果之前已经捡到了这个道具且这个道具还在生效中，则重置时间
					for (auto propTip : PropTipManager::getInstance()->propTipList) {
						if (propTip->getPropType() == prop->getPropType()) {
							propTip->reset();
							propEff(propTip);
							break;
						}
					}
				}
				
			}
		}
	}
}

/*
	主机与敌机碰撞检测
*/
void GameScene::collisionHeroAndEenmy() {
	for (Enemy* enemy : EnemyManager::getInstance()->enemyList) {
		//如果enemy为死亡状态
		if (!enemy->getLive()) {
			continue;
		}
		if (hero->getHeroState()) {
			bool isCrash = hero->getHeroRect().intersectsRect(enemy->getEnemyRect());
			if (isCrash) {
				if (hero->getInvincibleState()) {
					//英雄处于无敌状态
					enemy->die();
					break;
				} else {
					gameOver();
					break;
				}
			}
		}
	}
}

/*
	检测当前场景还有多少病毒
*/
void GameScene::checkCurrentEnemyCount() {
	int currentProportion = (currentEnemyCount / totalEnemyCount) * 100;
	progress_num->setString(std::to_string(currentProportion));
	progress->setPercent(currentProportion);
	if (currentProportion == 0) {
		uiNode->setVisible(false);
		//关闭默认调度器
		unscheduleUpdate();
		//初始化结算节点
		initSettlementNode();
		//切换关卡
		changeLevel();
		//停止英雄的移动
		hero->setMove(false);
		hero->isOpenShoot(false);
	}
}

/*
	道具效果
*/
void GameScene::propEff(PropTip* propTip) {
	propTip->onPropTipBegan = [this, propTip](bool flag) {
		switch (propTip->getPropType()) {
		case EnhancedRateOfFire:
			hero->isEnhancedRateOfFire(flag);
			break;
		case EnhancedFirepower:
			hero->isEnhancedFirepower(flag);
			break;
		case WeakenedVirus:
			//关闭病毒正常移动调度器
			unschedule(schedule_selector(GameScene::enemyNormalUpdate));
			//开启病毒缓慢移动调度器
			schedule(schedule_selector(GameScene::enemySlowUpdate), 0.1, -1, 0);
			break;
		case CallSupport:
			//暂时不写
			break;
		case PerformWonders:
			hero->setPerformWonders(flag);
			break;
		case RepulsiveShooting:
			break;
		case ChallengeVirus:
			//关闭病毒正常移动调度器
			unschedule(schedule_selector(GameScene::enemyNormalUpdate));
			//开启病毒缓慢移动调度器
			schedule(schedule_selector(GameScene::enemyFastUpdate), 0.1, -1, 0);
			break;
		case MegaloVirus:
			break;		
		case RestrictMovement:
			break;
		}
	};

	propTip->onPropTipEnded = [this, propTip](bool flag) {
		switch (propTip->getPropType()) {
		case EnhancedRateOfFire:
			hero->isEnhancedRateOfFire(flag);
			break;
		case EnhancedFirepower:
			hero->isEnhancedFirepower(flag);
			break;
		case WeakenedVirus:
			unschedule(schedule_selector(GameScene::enemySlowUpdate));
			schedule(schedule_selector(GameScene::enemyNormalUpdate), 0.1, -1, 0);
			break;
		case CallSupport:
			break;
		case PerformWonders:
			hero->setPerformWonders(flag);
			break;
		case RepulsiveShooting:
			break;
		case ChallengeVirus:
			unschedule(schedule_selector(GameScene::enemyFastUpdate));
			schedule(schedule_selector(GameScene::enemyNormalUpdate), 0.1, -1, 0);
			break;
		case MegaloVirus:
			break;
		case RestrictMovement:
			break;
		}
	};
}

/*
	增加金币
*/
void GameScene::addCoin(int coin, bool isGameCoin) {
	if (isGameCoin == true) {
		this->coin += coin;
		coin_num->setString(coinToString(this->coin));
	} else {
		this->totalCoin += coin;
		topCoinNum->setString(coinToString(this->totalCoin));
	}
}

/*
	将金币转换为.k的形式
*/
std::string GameScene::coinToString(int coin) {
	char temp[10];
	if (coin >= 1000) {
		sprintf_s(temp, "%.1fk", (float)coin / 1000);
	} else {
		sprintf_s(temp, "%d", coin);
	}
	string str(temp);
	return str.data();
}

/*
	增加金币运行的动画
*/
void GameScene::addCoinAction(Vec2 enemyPos, Size enemySize, 
	int coinNum,int level, bool isGameCoin, bool isPerformWonders) {
	for (size_t i = 0; i < level; i++) {
		//在病毒的身边炸裂金币，然后再移动到金币图标上
		int moveX = enemyPos.x + rand() % (int)(enemySize.width / 2) - enemySize.width / 4;
		int moveY = enemyPos.y + rand() % (int)(enemySize.height / 2) - enemySize.height / 4;
		
		Coin* coin = Coin::create(enemyPos, coinNum, isGameCoin, isPerformWonders);

		coin->setZOrder(2);
		addChild(coin);
		coin->runCoinAction(Vec2(moveX, moveY));
		CoinManager::getInstance()->addCoin(coin);
	}
}


/*
	暂停游戏
*/
void GameScene::pauseGame() {
	//暂停BGM 
	AudioUtil::getInstence()->stopBgm(true);
	//游戏背景变暗
	bg->setOpacity(150);
	//主机停止射击
	hero->isOpenShoot(false);
	//主机变为无敌
	hero->setInvincibleState(true);
	//关闭病毒正常移动调度器
	unschedule(schedule_selector(GameScene::enemyNormalUpdate));
	//开启病毒缓慢移动调度器
	schedule(schedule_selector(GameScene::enemySlowUpdate), 0.1, -1, 0);
}
/*
	继续游戏
*/
void GameScene::resumeGame() {
	//开启BGM 
	AudioUtil::getInstence()->playBgm();
	bg->setOpacity(255);
	hero->isOpenShoot(true);
	hero->setInvincibleState(false);
	unschedule(schedule_selector(GameScene::enemySlowUpdate));
	schedule(schedule_selector(GameScene::enemyNormalUpdate), 0.1, -1, 0);
} 

/*
	游戏结束
*/
void GameScene::gameOver() {
	//关闭默认调度器
	unscheduleUpdate();
	//主机死亡
	hero->die();
	//加载游戏结算界面
	initSettlementNode();
}

void GameScene::enemySlowUpdate(float dt) {
	//病毒速度变慢
	for (Enemy* enemy : EnemyManager::getInstance()->enemyList) {
		enemy->setEnemySpeed(EnemySpeed::slow);
	}
}

void GameScene::enemyNormalUpdate(float dt) {
	for (Enemy* enemy : EnemyManager::getInstance()->enemyList) {
		enemy->setEnemySpeed(EnemySpeed::Normal);
	}
}

/*
	//活化病毒调度器
*/
void GameScene::enemyFastUpdate(float dt){
	for (Enemy* enemy : EnemyManager::getInstance()->enemyList) {
		enemy->setEnemySpeed(EnemySpeed::Fast);
	}
}

/*
	切换关卡
*/
void GameScene::changeLevel() {
	char filename[20];
	for (size_t i = 0; i < 3; i++) {
		sprintf_s(filename, "num_%d", i + 1);
		FadeOut* fo = FadeOut::create(1.5f);
		FadeIn* fi = FadeIn::create(1.5f);
		int value = atoi(levelNums[i]->getStringValue().data()) + 1;
		CallFunc* call = CallFunc::create([this, i, value]() {
			levelNums[i]->setString(std::to_string(value));
		});
		Sequence* seqAct = Sequence::create(fo, call, fi, nullptr);
		levelNums[i]->runAction(seqAct);
		UserDefault::getInstance()->setIntegerForKey(filename, value);
	}
}